<?php
/**
 * Imagick 图像处理
 */

class Image_Imagick extends Image_Abstract {

    /*
     * 图像对象
     */
    protected $_im;

    /*
     * 图像宽度
     */
    protected $_width;

    /*
     * 图像高度
     */
    protected $_height;

    /*
     * 图像类型
     */
    protected $_type;

    /*
     * 支持类型
     */
    protected $_supportedType = array(
        Image::TYPE_GIF => array('gif', 'image/gif'),
        Image::TYPE_JPG => array('jpg', 'image/jpeg'),
        Image::TYPE_PNG => array('png', 'image/png'),
    );

    /*
     * 字符文件
     */
    private $_textFont='';

    /*
     * 构造方法
     */
    public function __construct($option=array()) {

        if (!class_exists('Imagick')) {
            throw new Image_Exception('Imagick not installed', Image_Exception::E_IMAGE_INIT_ERROR);
        }
        
        parent::__construct($option);
//        $this->_textFont = dirname(__FILE__) . '/fonts/Duality.ttf';
        if (isset($option['text_font']) && FS::isFile($option['text_font'])) {
             $this->setTextFont($option['text_font']);
        }
    }

    /*
     * 获取图像对象
     */
    public function getIm() {

        return $this->_im;
    }

    /*
     * 设置字符字体格式
     */
    public function setTextFont($fontFile) {

        if ($fontFile && FS::isFile($fontFile)) {
            $this->_textFont = $fontFile;
        }
    }

    /*
     * 创建图像
     * @param float  $width   图像宽
     * @param float  $height  图像高
     * @param string $bgColor 背景颜色
     * @param const  $type    图像类型
     */
    public function create($width, $height, $bgColor = '#FFFFFF', $type = Image::TYPE_JPG) {

        if (!$this->isSupport($type)) {
            throw new Image_Exception("The type of image is not supported", Image_Exception::E_IMAGE_PARAM_ERROR);
        }

        $this->_im = new Imagick();
        $this->_im->newImage($width, $height, $this->setColor($bgColor));
        $this->_im->setImageFormat($this->_supportedType[$type][0]);
        $this->_width = $width;
        $this->_height = $height;
        $this->_type = $type;
    }

    /*
     * 设置颜色
     * @param string $color 设置图像颜色，例如：#cc0033
     */
    private function setColor($color) {

        return new ImagickPixel($color);
    }

    /*
     * 图像融合
     */
    public function merge(Image_Abstract $im, $px, $py, $w, $h, $opacity = 100) {

        if (!($im->getIm() instanceof Imagick)) {
            throw new Exception('Object is not Instanceof Imagick',  Image_Exception::E_IMAGE_PARAM_ERROR);
        }

        // 设置im图像对象大小
        $im->getIm()->scaleImage($w,$h);

        if ($opacity < 100 && $opacity > 0){
            $im->getIm()->setImageOpacity($opacity);
        }
        $this->_im->compositeImage($im, Imagick::COMPOSITE_DEFAULT, $px, $py);
    }

    /**
     *
     * @param type $code    验证码字符串
     * @param type $width   验证码图像宽
     * @param type $height  验证码图像高
     */
    public function createCaptcha($code, $width = 200, $height = 60) {

        $this->create($width, $height, '#ffffff', Image::TYPE_PNG);
        $draw = new ImagickDraw();
        $color= new ImagickPixel();
        // 设置背景线
        for ($i = 0; $i < 50; $i++) {
            $h=  mt_rand(0, 10)/10;// 色调
            $s=  mt_rand(2,6)/10;// 饱和度
            $l=  0.7; // 亮度
            $color->setHSL($h, $s, $l);
            $sx = mt_rand(0, $width);
            $sy = mt_rand(0, $height);
            $draw->setFillColor($color);
            $ex = mt_rand($sx, $sx + 10);
            $ey = mt_rand($sy, $sy + 10);
            $draw->line($sx, $sy, $ex, $ey);
        }

        // 设置字符
        $leftPadding = $width / strlen($code) / 1.5; // 字符左侧留空
        $topPadding = $height / 1.3; // 字符右侧留空
        $draw->setFontSize(30);
        if ($this->_textFont) {
            $draw->setfont($this->_textFont);
        }
        for ($i = 1; $i <= strlen($code); $i++) {
            $h=  mt_rand(0, 10)/10;// 色调
            $s=  mt_rand(2,6)/10;// 饱和度
            $l=  0.5; // 亮度
            //$draw->setH
            
            $color->setHSL($h, $s, $l);
            $draw->setFillColor($color);
            $draw->annotation($leftPadding * $i + mt_rand(0, 3), $topPadding, $code[$i - 1]);
        }

        $this->_im->drawImage($draw);
    }

    /*
     * 读取图像
     * @param string $file 文件名
     */
    public function loadFromFile($file) {

        if (!file_exists($file)) {
            throw new Image_Exception('No Such Image File',  Image_Exception::E_IMAGE_PARAM_ERROR);
        }

        $this->_im = new Imagick();
        $this->_im->readImage($file);
        switch ($this->_im->getImageFormat()) {
            case 'GIF' : $this->_type = Image::TYPE_GIF;
                break;
            case 'JPEG' : $this->_type = Image::TYPE_JPG;
                break;
            case 'PNG' : $this->_type = Image::TYPE_PNG;
                break;
            default : throw new Exception('Your Image Type is not Supported!',  Image_Exception::E_IMAGE_TYPE_NOT_SUPPORT);
        }
        $this->_width = $this->_im->getImageWidth();
        $this->_height = $this->_im->getImageHeight();
    }

    /*
     * 调整图像大小
     * @param float $newWidth   图像目标宽
     * @param float $newHeight  图像目标高
     * @param const $resizeMode 图像截取类型
     */
    function resize($newWidth, $newHeight, $resizeMode = Image::RESIZE_STRETCH) {

        if ($newWidth < 0 || $newHeight < 0) {
            throw new Image_Exception('new width or height invalid',  Image_Exception::E_IMAGE_PARAM_ERROR);
        }

        switch ($resizeMode) {
            case Image::RESIZE_STRETCH :
                $this->_im->scaleImage($newWidth, $newHeight);
                break;
            case Image::RESIZE_SMART :
                $newWidth >= $newHeight ? $this->_im->scaleImage($newWidth, 0) : $this->_im->scaleImage(0, $newHeight);
                break;
            case Image::RESIZE_CENTER :
                $this->resize($newWidth, $newHeight,Image::RESIZE_SMART);
                //$xp = ($this->_width - $newWidth) / 2; // 左侧留空
                //$yp = ($this->_height - $newHeight) / 2; // 顶部留空
                $this->_im->cropImage($newWidth, $newHeight, 0, 0);
                break;
        }
    }

    /*
     *在图像上添加文字
     * @param string     $text 需要添加的文字
     * @param float      $px   文字所在的位置坐标x
     * @param float      $py   文字所在的位置坐标y
     * @param int        $fontSize 文字大小
     */
    public function addText($text, $px, $py, $color = '#FFFFFF', $fontSize = 5) {

        $draw = new ImagickDraw();
        $draw->setFontSize($fontSize);
        $draw->setFillColor($this->setColor($color));
        $draw->annotation($px, $py, $text);
        $this->_im->drawImage($draw);
    }

    /*
     * 图像格式是否支持
     * @param const $type 图像格式
     */
    public function isSupport($type) {

        if (!array_key_exists($type, $this->_supportedType)) {
            return false;
        }

        return true;
    }

    /*
     * 图像输出
     * @param const $target   输出类型
     * @param array =>file    文件名
     *              =>quality 图像品质
     *              =>type    图像类型
     */
    public function output($target = Image::OUTPUT_WEB_RESPONSE, $option = array()) {

        if (!empty($option['type'])) {
            $this->_type = $option['type'];
        }

        $quality = !empty($option['quality']) ? $option['quality'] : 80;
        //$this->addText($quality, 30, 30);
        $this->_im->setImageCompressionQuality($quality);
        switch ($target) {
            case Image::OUTPUT_FILE :
                if (!isset($option['file'])) {
                    throw new Image_Exception('no file name!',  Image_Exception::E_IMAGE_PARAM_ERROR);
                }

                if (isset($option['type'])) {
                    $this->_im->setImageFormat($this->_supportedType[$this->_type][0]);
                }
                $this->_im->writeImage($option['file']);
                break;
            case Image::OUTPUT_BROWSER :
                $this->_im->setImageFormat($this->_supportedType[$this->_type][0]);
                header('Content-type:' . $this->_supportedType[$this->_type][1]);
                echo $this->_im;
                break;
            default :
                $response = Web_Response::getInstance();
                $response->setNoCache();
                $response->setHeader('content-type', $this->_supportedType[$this->_type][1]);
                $response->setOutputObContent(false);
                $response->setBody($this->_im);
                $response->output();
                //echo ;
                break;
        }
        $this->_im->destroy();
    }
}

